package treinadores;
import static java.lang.Math.*;

public class CalculosAuxiliares {
	
	public static int getIndiceRoboMenorDistancia(int posicaoRoboNossoTime, int [] posicaoTimeAdversario){
	   Posicao posicaoR1 = getPosicao(posicaoRoboNossoTime);
	   
		   double menorDistancia = Double.MAX_VALUE;
		   int indiceMenorDistancia = 0;
	   
		   for(int i = 0; i < posicaoTimeAdversario.length; i++){
			   int roboAdversario = posicaoTimeAdversario[i];
			   if(posicaoR1.getDistancia(getPosicao(roboAdversario)) < menorDistancia)
			   {
			        menorDistancia = posicaoR1.getDistancia(getPosicao(roboAdversario));
			        indiceMenorDistancia = i;
			   }
		   }
		   
		   return indiceMenorDistancia;
	   }
	
	public static int acharPosicaoMenorDistanciaParaPermanecer(int posicaoJogador, int posicaoAdversario){
		int colunaRobo2 = posicaoAdversario%4;
		
		if(posicaoJogador >= 4){
			//O jogador deve voltar
			posicaoJogador = (posicaoAdversario/4)*4-4+colunaRobo2;
		}
		else
		{
			//mantém na defesa e vai na casa do adversário
			posicaoJogador = (posicaoJogador/4)*4+colunaRobo2;
		}
		
		return posicaoJogador;
	}
	
	public static int acharPosicaoMaiorDistanciaParaAvanco(int posicaoRobo1, int posicaoRobo2)
	{
		int colunaRobo2 = posicaoRobo2%4;
		int posicaoMaisDistanteRobo2 = 0;
		
		switch(colunaRobo2){
		case 0:
			posicaoMaisDistanteRobo2 = 3;
			break;
		case 1:
			posicaoMaisDistanteRobo2 = 3;
			break;
		case 2: 
			posicaoMaisDistanteRobo2=0;
			break;
		case 3:
			posicaoMaisDistanteRobo2 = 0;
			break;
		}
		
		if(posicaoRobo1 < 12){
			posicaoRobo1 = (posicaoRobo1/4)*4+4+posicaoMaisDistanteRobo2;
		}
		else
		{
			posicaoRobo1 = (posicaoRobo1/4)*4 + posicaoMaisDistanteRobo2;
		}
		return posicaoRobo1;
	}
	
	public static Posicao getPosicao(int posicaoRobo){
		switch(posicaoRobo)
		{
			case 0:
				return new Posicao(0,0);
			case 1:
				return new Posicao(0,1);
			case 2:
				return new Posicao(0,2);
			case 3:
				return new Posicao(0,3);
			case 4:
				return new Posicao(1,0);
			case 5:
				return new Posicao(1,1);
			case 6:
				return new Posicao(1,2);
			case 7:
				return new Posicao(1,3);
			case 8:
				return new Posicao(2,0);
			case 9:
				return new Posicao(2,1);
			case 10:
				return new Posicao(2,2);
			case 11:
				return new Posicao(2,3);
			case 12:
				return new Posicao(3,0);
			case 13:
				return new Posicao(3,1);
			case 14:
				return new Posicao(3,2);
			case 15:
				return new Posicao(3,3);
		}
		return null;
	}
	
	public static double [] toBinaryDouble(int numero){
		double [] number;
//		int tamanhoVetor = (int) ceil(sqrt(numero));
		int tamanhoVetor = 4;
		number = new double[tamanhoVetor];
		
		int indiceVetor = tamanhoVetor-1;
		
		while(numero != 0 && indiceVetor >= 0){
			number[indiceVetor] = numero%2;
			numero /= 2;
			indiceVetor--;
		}
		return number;
	}
	
	public static double [] toBinaryDouble2(int numero){
		double [] number;
//		int tamanhoVetor = (int) ceil(sqrt(numero));
		int tamanhoVetor = 2;
		number = new double[tamanhoVetor];
		
		int indiceVetor = tamanhoVetor-1;
		
		while(numero != 0 && indiceVetor >= 0){
			number[indiceVetor] = numero%2;
			numero /= 2;
			indiceVetor--;
		}
		return number;
	}
	
	public static double [] getSaidaDesejada(int posicaoJogador,int[] posicoesAdversarios) {
		int roboMaisProximo = CalculosAuxiliares.getIndiceRoboMenorDistancia(
				posicaoJogador, posicoesAdversarios);
		return CalculosAuxiliares.toBinaryDouble(CalculosAuxiliares
				.acharPosicaoMaiorDistanciaParaAvanco(posicaoJogador,
						posicoesAdversarios[roboMaisProximo]));
	}
	
	public static double [] getSaidaDesejadaPermanecer(int posicaoJogador, int[] posicoesAdversarios) {
		int roboMaisProximo = CalculosAuxiliares.getIndiceRoboMenorDistancia(
				posicaoJogador, posicoesAdversarios);
		return CalculosAuxiliares.toBinaryDouble(CalculosAuxiliares
				.acharPosicaoMenorDistanciaParaPermanecer(posicaoJogador,
						posicoesAdversarios[roboMaisProximo]));
	}
	
	/**
	 * Tenta achar uma coluna para o jogador passar
	 * @return
	 */
	
	public static int acharColunaVaziaAvancar(int posicaoJogador, int [] posicaoJogadores){
	    //varre a lista e procura a posição mais próxima daonde o jogador está
	    //que esteja disponível para ele passar
		//Coluna com preferência pra ser usada
		int colunaFavorita = posicaoJogador%4;
		
		if(colunaDisponivelAvancar(posicaoJogadores, posicaoJogador, colunaFavorita))
		{
			return colunaFavorita;
		}
		
		int colunaSuperior = colunaFavorita+1;
		int colunaInferior = colunaFavorita-1;
		
		while(colunaSuperior <= 3 || colunaInferior >= 0)
		{
			if(colunaDisponivelAvancar(posicaoJogadores,posicaoJogador,colunaSuperior) && colunaSuperior <=3){
				return colunaSuperior;
			}
			else if(colunaDisponivelAvancar(posicaoJogadores,posicaoJogador,colunaInferior) && colunaInferior >= 0){
				return colunaInferior;
			}
			colunaSuperior++;
			colunaInferior--;
		}
		
		//Caso não dê certo, vai pela mais próxima mesmo.		
		return colunaFavorita;		
	}
	
	/**
	 * Tenta achar uma coluna para o jogador passar
	 * @return
	 */
	
	public static int acharColunaVaziaRetornar(int posicaoJogador, int [] posicaoJogadores){
	    //varre a lista e procura a posição mais próxima daonde o jogador está
	    //que esteja disponível para ele passar
		//Coluna com preferência pra ser usada
		int colunaFavorita = posicaoJogador%4;
		
		if(colunaDisponivelRetornar(posicaoJogadores, posicaoJogador, colunaFavorita))
		{
			return colunaFavorita;
		}
		
		int colunaSuperior = colunaFavorita+1;
		int colunaInferior = colunaFavorita-1;
		
		while(colunaSuperior <= 3 || colunaInferior >= 0)
		{
			if(colunaDisponivelRetornar(posicaoJogadores,posicaoJogador,colunaSuperior) && colunaSuperior <=3){
				return colunaSuperior;
			}
			else if(colunaDisponivelRetornar(posicaoJogadores,posicaoJogador,colunaInferior) && colunaInferior >= 0){
				return colunaInferior;
			}
			colunaSuperior++;
			colunaInferior--;
		}
		
		//Caso não dê certo, vai pela mais próxima mesmo.		
		return colunaFavorita;		
	}
	
	public static boolean colunaDisponivelAvancar(int [] posicaoJogadores, int posicaoJogador, int colunaFavorita){
		for (int posicaoAdversario : posicaoJogadores) {
			if(posicaoAdversario%4 == colunaFavorita && 
					((posicaoAdversario/4)-1) == (posicaoJogador/4))
			{
				return false;
			}
		}
		return true;
	}
	
	public static boolean colunaDisponivelRetornar(int [] posicaoJogadores, int posicaoJogador, int colunaFavorita){
		for (int posicaoAdversario : posicaoJogadores) {
			if(posicaoAdversario%4 == colunaFavorita && 
					((posicaoAdversario/4)+1) == (posicaoJogador/4))
			{
				return false;
			}
		}
		return true;
	}
}

class Posicao{
	public int linha;
	public int coluna;
	
	public Posicao(int linha, int coluna){
		this.linha = linha;
		this.coluna = coluna;
	}
	
	public double getDistancia(Posicao posicao2){
		return sqrt(pow(this.linha-posicao2.linha,2)+pow(this.coluna-posicao2.coluna,2));
	}
}
